package com.fc.remoting.protocol;

import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.helpers.FormattingTuple;
import org.slf4j.helpers.MessageFormatter;
import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

import com.fc.commons.AnnotationUtility;
import com.fc.remoting.anno.Protocol;
import com.fc.remoting.message.Commond;

@Component
public class ProtocolRegister implements BeanPostProcessor {
	private static final Logger logger = LoggerFactory.getLogger(ProtocolRegister.class);

	/** 指令->指令信息，映射表 */
	private static ConcurrentHashMap<Commond, ProtocolAdapter> infos = new ConcurrentHashMap<Commond, ProtocolAdapter>();

	// 扫描运行时的 Bean 完成注册的相关方法
	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		Class<?> clazz = AnnotationUtility.findAnnotationDeclaringClassAndInterface(Protocol.class, bean.getClass());
		if (clazz == null) {
			return bean;
		}
		Protocol handler = clazz.getAnnotation(Protocol.class);
		if (handler != null) {
			// 创建指令对象
			Commond commond = Commond.valueOf(handler.module(), handler.order());
			// 进行注册
			try {
				ProtocolAdapter processer = ProtocolAdapter.valueOf((IProtocol) bean);
				ProtocolAdapter prev = infos.put(commond, processer);
				if (prev != null) {
					FormattingTuple message = MessageFormatter.format("指令[{}]重复注册:{}", commond.toString(), processer);
					logger.error(message.getMessage());
				} else {
					logger.info("完成指令注册:{}", commond.toString());
				}
			} catch (Exception e) {
				FormattingTuple message = MessageFormatter.format("注册指令[{}]失败", commond.toString());
				logger.error(message.getMessage());
				throw new FatalBeanException(message.getMessage(), e);
			}
		}
		return bean;
	}

	/**
	 * 移除已经注册的指令
	 * 
	 * @param command
	 *            指令
	 */
	public void unregister(Commond command) {
		infos.remove(command);
	}

	/**
	 * 是否包含指定的指令
	 * 
	 * @param command
	 *            指令
	 * @return
	 */
	public boolean contain(Commond command) {
		return infos.contains(command);
	}

	/**
	 * 获取对应的{@link ProtocolAdapter}
	 * 
	 * @param command
	 *            指令
	 * @return 指定对应的处理器，不会返回null
	 * @throws ProcessorNotFound
	 *             处理器不存在时抛常
	 */
	public static ProtocolAdapter getAdapter(Commond order) {
		ProtocolAdapter cp = infos.get(order);
		if (cp == null || !cp.hasProcessor()) {
			FormattingTuple message = MessageFormatter.format("指令[{}]对应的业务处理器不存在", order);
			if (logger.isDebugEnabled()) {
				logger.debug(message.getMessage());
			}
			throw new NullPointerException(message.getMessage());
		}
		return cp;
	}

	/**
	 * 获取全部已经注册的指令集
	 * 
	 * @return
	 */
	// public Set<Integer> getProtocolInfos() {
	// return new HashSet<Integer>(infos.keySet());
	// }

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}
}